package cn.com.fuhuitong.http

import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.SPStaticUtils
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okio.Buffer
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.*
import java.util.concurrent.TimeUnit


object HttpServiceFactory {

    private fun client() = OkHttpClient.Builder()
        .writeTimeout(30.toLong(), TimeUnit.SECONDS)
        .readTimeout(30.toLong(), TimeUnit.SECONDS)
        .connectTimeout(30.toLong(), TimeUnit.SECONDS)
//        .addInterceptor(SigningInterceptor())
        .addInterceptor(LoggingInterceptor())

    fun <ApiService> create(clazz: Class<ApiService>, baseUrl: String): ApiService {
        val retrofit = Retrofit.Builder()
            .client(client().build())
            .baseUrl(baseUrl)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()
        return retrofit.create(clazz)
    }

    /**
     * 拦截添加请求头 并刷新token
     */
    internal class SigningInterceptor : Interceptor {

        override fun intercept(chain: Interceptor.Chain): Response {
            val token: String = SPStaticUtils.getString("token")

            val request: Request = chain.request().newBuilder()
                .build()
            val response: Response = chain.proceed(request)
            if (response.code == 401) {
                return chain.proceed(
                    chain.request().newBuilder()
                        .addHeader("token", token)
                        .build()
                )
            }
            return response
        }
    }

    /**
     * Log拦截
     */
    internal class LoggingInterceptor : Interceptor {

        private val mediaType: MediaType = "application/octet-stream".toMediaTypeOrNull()!!

        override fun intercept(chain: Interceptor.Chain): Response {

            //发送时截取数据
            val request = chain.request()
            val t1 = System.nanoTime()
            val body = request.body
            val buffer = Buffer()
            body?.writeTo(buffer)

            val send = String.format(
                Locale.CHINA, ("发送请求:%s%n请求JSON:%s"),
                request.url,
                buffer.readUtf8()
            )
            LogUtils.d(send)

            //接收时截取数据
            val response = chain.proceed(request)
            val t2 = System.nanoTime()
            val responseBody = response.peekBody((1024 * 1024).toLong())

            val accept = String.format(
                Locale.CHINA, ("接收响应:%s%n请求时间:%.1fms%n报文信息:%s返回JSON:%s"),
                response.request.url,
                (t2 - t1) / 1e6,
                response.headers,
                if (responseBody.contentType() == mediaType)
                    "This is the file download" else responseBody.string()
            )
            LogUtils.d(accept)

            return response
        }
    }
}